﻿#include "../Utils/Utils.h"

#include "CInventory.h"
#include "CInventoryTransaction.h"

#include "../Memory/GameData.h"

void C_Inventory::dropSlot(int slot) {
	// FillingContainer::dropSlot
	using drop_t = void(__fastcall*)(C_Inventory*, int, char);
	static drop_t func = reinterpret_cast<drop_t>(Utils::Utils::getBase() + 32392112);
	func(this, slot, 0i8);
}

void C_Inventory::dropAll() {
	for (int i = 0; i < 36; ++i)
		dropSlot(i);
}

bool C_Inventory::isFull() {
	int fullslots = 0;
	for (int i = 0; i < 36; ++i)
		if (this->getItemStack(i)->item != nullptr) [[likely]]
			++fullslots;

	if (fullslots == 36)
		return true;
	return false;
}

void C_ContainerScreenController::handleAutoPlace(uintptr_t a1, std::u8string_view name, int slot) {
	using ContainerScreenController__autoPlace = __int64(__fastcall*)(C_ContainerScreenController*, uintptr_t, TextHolder, int);
	static ContainerScreenController__autoPlace autoPlaceFunc = reinterpret_cast<ContainerScreenController__autoPlace>(Utils::Utils::getBase() + 12091872);
	autoPlaceFunc(this, a1, TextHolder(name), slot);
}

void C_Inventory::moveItem(int from, int to = -1) {
	C_InventoryTransactionManager* manager = GameData::getLocalPlayer()->getTransactionManager();

	uintptr_t sigOffset = Utils::Utils::getBase() + 9996733;
	int offset = *reinterpret_cast<int*>(sigOffset + 3);
	C_ItemStack* emptyItemStack = reinterpret_cast<C_ItemStack*>(sigOffset + offset + /*length of instruction*/ 7);

	if (to < 0)
		to = getFirstEmptySlot();
	C_ItemStack* item1 = getItemStack(from);
	C_ItemStack* item2 = getItemStack(to);

	if (item1->item == nullptr) [[unlikely]]
		return;
	if (item2->item == nullptr) [[unlikely]] {
		C_InventoryAction first(from, item1, nullptr);
		C_InventoryAction second(to, nullptr, item1);
		manager->addInventoryAction(first);
		manager->addInventoryAction(second);
		*item2 = *item1;
		*item1 = *emptyItemStack;
	} else {
		C_InventoryAction first(from, item1, nullptr);
		C_InventoryAction second(to, item2, item1);
		C_InventoryAction third(from, nullptr, item2);
		manager->addInventoryAction(first);
		manager->addInventoryAction(second);
		manager->addInventoryAction(third);
		C_ItemStack a = *item2;
		*item2 = *item1;
		*item1 = a;
	}
}

void C_Inventory::swapSlots(int from, int to) {
	C_InventoryTransactionManager* manager = GameData::getLocalPlayer()->getTransactionManager();
	C_ItemStack* i1 = getItemStack(from);
	C_ItemStack* i2 = getItemStack(to);
	C_InventoryAction first(from, i1, nullptr);
	C_InventoryAction second(to, i2, i1);
	C_InventoryAction third(from, nullptr, i2);
	manager->addInventoryAction(first);
	manager->addInventoryAction(second);
	manager->addInventoryAction(third);
}